<?php
namespace app\api\controller;
use think\Controller;
use think\Db;
class Pay extends Controller
{
    /**
    * 获取订单列表
    * @return bool
    * @return int $orderNo 订单编号
    */
    public function index()
    {
        $orderNo = input('param.orderNo');
        if(!$orderNo){
            json_msg(1,'请求错误!');
        }
        $order = Db::name('goods_order')->field('order_no,pay_money')->where('order_no', $orderNo)->find();
        json_msg_data(0,'ok',$order);
    }
    /**
    * 获取微信支付参数
    * @return bool
    * @return int $orderNo 订单编号
    * @return int $userId 用户id
    * @return int $payMoney 支付金额
    */
    public function getWechatConfig($orderNo, $userId, $payMoney)
    {
        if(!$orderNo || !$userId || !$payMoney){
            json_msg(1,'请求错误');
        }
        $out_trade_no = $orderNo; //自定义订单号
        $openid = get_user_info_data($userId, 'xwx_openid'); // 用户openid
        $total_fee = ceil($payMoney * 100);//支付金额
        // $total_fee = 1;//支付金额
        $body = '购买商品';//商品描述
        $notify_url = sysconf('website') . '/index/pay/notify/';//回调地址
        $trade_type = 'JSAPI';//交易类型 具体看API 里面有详细介绍
        $appid = sysconf('xwx_appid');//商户小程序账号appid
        $mch_id = sysconf('wx_mchid');//商户号 微信官方的
        $key = sysconf('wx_partnerkey');//支付秘钥
        $nonce_str = $this->createNoncestr();//随机字符串
        $spbill_create_ip = $_SERVER["REMOTE_ADDR"]; //获得用户设备IP
        $attach = 'atach';//支付成功后原样返回的标识
        $array = [
            'appid' => $appid,
            'mch_id' => $mch_id,
            'nonce_str' => $nonce_str,
            'openid' => $openid,
            'attach' => $attach,
            'body' => $body,
            'out_trade_no' => $out_trade_no,
            'total_fee' => $total_fee,
            'notify_url' => $notify_url,
            'trade_type' => $trade_type,
            'spbill_create_ip' => $spbill_create_ip,
        ];
        $sign = $this->getSign($array);
        $array['sign'] = $sign;
        $xml = $this->arrayToXml($array);
        $url = "https://api.mch.weixin.qq.com/pay/unifiedorder";
        $getXml = $this->postXmlCurl($xml, $url);
        $dataxml = $this->xmlToArray($getXml);
        if($dataxml['return_code'] == 'SUCCESS'){
			$noncestr = md5('456465da');//随机字符串

			$timestamp = (string)time();//当前时间戳

			$prepay_id = $dataxml['prepay_id'];

			$package= "prepay_id=$prepay_id";

			$signType = 'MD5';

            $paySign = strtoupper(MD5("appId=$appid&nonceStr=$noncestr&package=$package&signType=$signType&timeStamp=$timestamp&key=$key"));

            
            $data['timeStamp'] = $timestamp;

            $data['nonceStr'] = $noncestr;
            
            $data['package'] = $package;

            $data['signType'] = $signType;

            $data['paySign'] = $paySign;

            json_msg_data(0,'ok',$data);

		}else{
            json_msg(1,'支付失败');
        }
    }

    /**
    * 微信支付
    * @return bool
    * @return int $orderNo 订单编号
    * @return int $userId 用户id
    * @return int $payMoney 支付金额
    */
    public function wechatPay()
    {
        $orderNo = input('param.orderNo');
        $payMoney = input('param.payMoney');
        $userId = input('param.userId');
        $payType = 1;
        $newOrderNo = 'GM' . date('ymdHis', time()) . mt_rand(1000, 9999);
        Db::name('goods_order')->where('order_no', $orderNo)->update(['pay_type' => $payType, 'pay_money' => $payMoney, 'order_no' => $newOrderNo]);
        Db::name('goods_order_detail')->where('order_no',$orderNo)->update(['order_no' => $newOrderNo]);
        $data = $this->getWechatConfig($newOrderNo, $userId, $payMoney);
        if ($data) {
            json_msg_data(0, 'success', $data);
        } else {
            json_msg_data(1, '当前订单存在异常，不能使用支付');
        }
    }

    public function balanceWechatPay()
    {
        $orderNo = input('param.orderNo');
        $payMoney = input('param.payMoney');
        $payType = input('param.payType');
        $balance = get_user_info_data(session('userId'), 'balance');
        $payMoney = $payMoney - $balance;
        $newOrderNo = 'GM' . date('ymdHis', time()) . mt_rand(1000, 9999);
        Db::name('goods_order')->where('order_no', $orderNo)->update(['pay_type' => $payType, 'balance' => $balance, 'order_no' => $newOrderNo]);
        Db::name('goods_order_detail')->where('order_no',$orderNo)->update(['order_no' => $newOrderNo]);
        $data = $this->getWechatConfig($newOrderNo, session('userId'), $payMoney);

        if ($data) {
            json_msg_data(0, 'success', $data);
        } else {
            json_msg_data(1, '当前订单存在异常，不能使用支付');
        }
    }

    /**
    * 余额支付
    * @return bool
    * @return int $orderNo 订单编号
    */
    public function balancePay()
    {
        $orderNo = input('param.orderNo');
        $order = Db::name('goods_order')->where('order_no', $orderNo)->find();
        $balance = get_user_info_data($order['user_id'], 'balance');
        if ($balance < $order['pay_money']) {
            json_msg(1, '余额不足');
        }
        $result = Db::name('user')->where('id', $order['user_id'])->setDec('balance', $order['pay_money']);
        post_user_balance_log($order['user_id'],'-',$order['pay_money'],'购买商品','2',$order['id']);
        if ($result) {
            Db::name('goods_order')->where('order_no', $orderNo)->update(['pay_type' => 0]);
            $this->putOrderInfo($orderNo);
            json_msg(0, '支付成功');
        } else {
            json_msg(1, '支付失败');
        }
    }

    //异步通知url，商户根据实际开发过程设定
    public function notify()
    {
        //使用通用通知接口
        //存储微信的回调
        // $xml = $GLOBALS['HTTP_RAW_POST_DATA'];
        $xml = file_get_contents("php://input");

        $array = $this->xmlToArray($xml);
        $filename = '1.txt';
        file_put_contents($filename, json_encode($array, 320));
//        die;
        if ($array['result_code'] == 'SUCCESS' && $array['return_code'] == 'SUCCESS') {
            $orderNo = $array['out_trade_no'];
            $payStatus = Db::name('goods_order')->where('order_no', $orderNo)->value('status');
            if ($payStatus ==  0) {
                $this->putOrderInfo($orderNo);
            }
            return $this->arrayToXml(['return_code' => 'SUCCESS', 'return_msg' => 'OK']);
            echo "SUCCESS";
        } else {
            return $this->arrayToXml(['return_code' => 'FAIL', 'return_msg' => 'error']);
            echo "FAIL";
        }

    }

    /*
     * 订单支付成功之后的处理
     * */
    public function putOrderInfo($orderNo)
    {
        /*获取订单信息*/
        $order = Db::name('goods_order')->where('order_no', $orderNo)->find();
        $userId = $order['user_id'];
        /*分销比例*/
        $distribution_ratio = sysconf('distribution_ratio')/100;
        /*上级用户id*/
        $firstUserId = get_user_previou($userId);

        /*订单详情*/
        $orderDetail = Db::name('goods_order_detail')->where('order_no', $orderNo)->select();
        foreach ($orderDetail as $k => $v) {
            Db::name('goods')->where('id', $v['goods_id'])->setInc('sell_count', $v['goods_count']);
        }
        $userModel = Db::name('user');
        if ($firstUserId) {
            /*一级用户*/
            $userModel->where('id', $firstUserId)->setInc('balance', $order['sum'] *  $distribution_ratio);
            post_distribution_log($userId, $order['sum'] *  $distribution_ratio, $firstUserId, $orderNo, 0,$order['sum'], '商品', 1);
            
        }
           
        
        $data = [
            'status' => 1,
            'pay_time' => date('Y-m-d H:i:s')
        ];
        Db::name('goods_order')->where('order_no', $orderNo)->update($data);
    }

    /**
     *    作用：格式化参数，签名过程需要使用
     */
    function formatBizQueryParaMap($paraMap, $urlencode)
    {
        $buff = "";
        ksort($paraMap);
        foreach ($paraMap as $k => $v) {
            if ($urlencode) {
                $v = urlencode($v);
            }
            //$buff .= strtolower($k) . "=" . $v . "&";
            $buff .= $k . "=" . $v . "&";
        }
        $reqPar = '';
        if (strlen($buff) > 0) {
            $reqPar = substr($buff, 0, strlen($buff) - 1);
        }
        return $reqPar;
    }

    /**
     *    作用：生成签名
     */
    public function getSign($Obj)
    {
        foreach ($Obj as $k => $v) {
            $Parameters[$k] = $v;
        }
        //签名步骤一：按字典序排序参数
        ksort($Parameters);
        $String = $this->formatBizQueryParaMap($Parameters, false);
        //签名步骤二：在string后加入KEY
        $String = $String . "&key=" . sysconf('wx_partnerkey');
        //签名步骤三：MD5加密
        $String = md5($String);
        //签名步骤四：所有字符转为大写
        $result_ = strtoupper($String);
        return $result_;
    }

    /**
     *    作用：array转xml
     */
    function arrayToXml($arr)
    {
        $xml = "<xml>";
        foreach ($arr as $key => $val) {
            if (is_numeric($val)) {
                $xml .= "<" . $key . ">" . $val . "</" . $key . ">";
            } else
                $xml .= "<" . $key . "><![CDATA[" . $val . "]]></" . $key . ">";
        }
        $xml .= "</xml>";
        return $xml;
    }

    /**
     *    作用：将xml转为array
     */
    public function xmlToArray($xml)
    {
        //将XML转为array
        $array_data = json_decode(json_encode(simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA)), true);
        return $array_data;
    }

    /**
     * 获取prepay_id
     */
    public function getPrepayId()
    {
        $this->postXml();
        $this->result = $this->xmlToArray($this->response);
        $prepay_id = $this->result["prepay_id"];
        return $prepay_id;
    }

    function trimString($value)
    {
        $ret = null;
        if (null != $value) {
            $ret = $value;
            if (strlen($ret) == 0) {
                $ret = null;
            }
        }
        return $ret;
    }

    /**
     *    作用：产生随机字符串，不长于32位
     */
    public function createNoncestr($length = 32)
    {
        $chars = "abcdefghijklmnopqrstuvwxyz0123456789";
        $str = "";
        for ($i = 0; $i < $length; $i++) {
            $str .= substr($chars, mt_rand(0, strlen($chars) - 1), 1);
        }
        return $str;
    }

    /**
     *    作用：以post方式提交xml到对应的接口url
     */
    public function postXmlCurl($xml, $url, $second = 30)
    {
        //初始化curl
        $ch = curl_init();
        //设置超时
        curl_setopt($ch, CURLOP_TIMEOUT, $second);
        //这里设置代理，如果有的话
        //curl_setopt($ch,CURLOPT_PROXY, '8.8.8.8');
        //curl_setopt($ch,CURLOPT_PROXYPORT, 8080);
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
        //设置header
        curl_setopt($ch, CURLOPT_HEADER, FALSE);
        //要求结果为字符串且输出到屏幕上
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
        //post提交方式
        curl_setopt($ch, CURLOPT_POST, TRUE);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $xml);
        //运行curl
        $data = curl_exec($ch);
        curl_close($ch);
        //返回结果
        if ($data) {
            curl_close($ch);
            return $data;
        } else {
            $error = curl_errno($ch);
            echo "curl出错，错误码:$error" . "<br>";
            echo "<a href='http://curl.haxx.se/libcurl/c/libcurl-errors.html'>错误原因查询</a></br>";
            curl_close($ch);
            return false;
        }
    }

    
}